package eclipse.client.threadpool;
import eclipse.*;
import eclipse.client.Database;
import eclipse.lib.sockets.*;
import eclipse.util.*;
/**
 * Performs simple executions of code and checks
 */
/*
 * Copyright (c) 2009, TOD Productions All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *	- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *	- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *	-Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
public final class MainLoopThread extends ThreadedTimer 
{	
	//skips to do (network)
	private int skip = 0;
	//latency in ms (network)
	private final int latency;
	//set the latency and build the object
	public MainLoopThread(LATENCY lag)
	{
		//output the latency
		System.out.println("Latency: " + lag);
		//if its set to low latency
		if(lag == LATENCY.LOW)
		{
			//set it to 23
			latency = 23;
		}
		//if its set to medium latency
		else if(lag == LATENCY.MEDIUM)
		{		//set it to 15
			latency = 15;
		}
		//if its set to hight latency
		else if(lag == LATENCY.HIGH)
		{	//set it to 10
			latency = 10;
		}
		//if using dial-up
		else if(lag == LATENCY.EXTRAHIGH)
		{//run at 12 fps
			latency = 5;
		}
		else
		{
			latency = 30;
		}
		
		//enable the thread
		setEnabled(true);
		//compute how frequently it should process network data
		setInterval(1000/latency);
		//set the name of the thread
		setName("Main Loop Thread");
		//start the thread
		start();		
	}
	//code to execute every x miliseconds 
	public final void tick()
	{
		//if there is no player then exit 
		if(Database.player == null)
		{
			//exit the current process
			return;
		}
		//check if movements should be processed
		checkMovement();				
		//draw any animations
		animate();
	}	
	//updates the animations
	public final void animate()
	{		
		//if the player is not moving then exit
		if(!Database.player[Database.myID].character.cMoving)
		{			
			return;
		}
		//update the skip count
		skip++;
		//if the skip count is divisible by 4
		if((skip % 4 == 0))			
		{
			//update the frame count
			int frame = Database.player[Database.myID].character.cFrame;
			//as long as its less than the max number of frames 
			//TODO: get a max_frame value for sprites
			if(frame < 3)
			{
				//update the frame			
				frame++;
			}
			else
			{
				frame = 0;
			}
			//set the player's frame
			Database.player[Database.myID].character.cFrame = frame;
		}		
		//send date to the server
		ClientDataHandle.sendCharPosition();
	}
	//check if the player moved
	public final void checkMovement()
	{
		//if there is no draw surface or player array then exit
		if(Database.glInterface == null || Database.player == null)
			return;
		
		//if the player character does not exist then exit
		if(Database.player[Database.myID] == null)
			return;
		
		//value to update the movement by
		final float moveVal = 2f * (30f/latency);
		//get the move value by math		
		
		//if left is pressed
		if(Database.glInterface.getLeft())			
		{
			//copy the moveval to another float
			float lMoveVal = moveVal;
			//if up or down is pressed, then move less left
			if(Database.glInterface.getUp() || Database.glInterface.getDown())
				lMoveVal /= 1.5f;
			//update the player's x position
			Database.player[Database.myID].character.cPos.x =
				Database.player[Database.myID].character.cPos.x - lMoveVal;
			//update the direction the player is facing
			Database.player[Database.myID].character.cDir = Constants.DIR_LEFT;
			//state that the player is moving
			Database.player[Database.myID].character.cMoving = true;
		}
		//if right is pressed instead
		else if(Database.glInterface.getRight())
		{
			//copy the moveval to another float
			float lMoveVal = moveVal;
			//if up or down is pressed then move less
			if(Database.glInterface.getUp() || Database.glInterface.getDown())
				lMoveVal /= 1.5f;
			//update the player's x position
			Database.player[Database.myID].character.cPos.x =
				Database.player[Database.myID].character.cPos.x + lMoveVal;
			//update the direction the player is facing
			Database.player[Database.myID].character.cDir = Constants.DIR_RIGHT;
			//state that the player is moving
			Database.player[Database.myID].character.cMoving = true;
		}
		//if up is pressed
		if(Database.glInterface.getUp())
		{
			//copy the movevalue to another float
			float lMoveVal = moveVal;
			//if left or right is pressed then move less
			if(Database.glInterface.getLeft() || Database.glInterface.getRight())
				lMoveVal /= 1.5f;
			//update the player's y position
			Database.player[Database.myID].character.cPos.y =
				Database.player[Database.myID].character.cPos.y - lMoveVal;
			//update the player's direction
			Database.player[Database.myID].character.cDir = Constants.DIR_UP;
			//state that the player is moving
			Database.player[Database.myID].character.cMoving = true;
		}
		//if down is pressed instead
		else if(Database.glInterface.getDown())
		{
			//copy the moveval to another float
			float lMoveVal = moveVal;
			//if left or right is pressed move less
			if(Database.glInterface.getLeft() || Database.glInterface.getRight())
				lMoveVal /= 1.5f;
			//update the player's y position
			Database.player[Database.myID].character.cPos.y =
				Database.player[Database.myID].character.cPos.y + lMoveVal;
			//change the player's direection to down
			Database.player[Database.myID].character.cDir = Constants.DIR_DOWN;
			//state that the player is moving
			Database.player[Database.myID].character.cMoving = true;
		}
		//if there is no movement at all
		if(!Database.glInterface.getDown() && !Database.glInterface.getUp() &&
			!Database.glInterface.getLeft() && !Database.glInterface.getRight()
		)
		{
			//check to confirm if the player was just moving
			if(Database.player[Database.myID].character.cMoving)
			{
				//set the movement to false
				Database.player[Database.myID].character.cMoving = false;
				//reset the frame
				Database.player[Database.myID].character.cFrame = 0;
				//send the player's movement
				ClientDataHandle.sendCharPosition();
			}
		}
	}
}
